home *** CD-ROM | disk | FTP | other *** search
/ FishMarket 1.0 / FishMarket v1.0.iso / fishies / 301-325 / disk_319 / cnewssrc / cnews.src.lzh / libc / fgetmfs.c < prev    next >
C/C++ Source or Header  |  1989-07-15  |  3KB  |  138 lines

  1. /*
  2.  * fgetmfs - read an arbitrarily long, possibly continued line;
  3.  * return a pointer to it, in malloced memory.
  4.  */
  5.  
  6. #include <stdio.h>
  7. #include <ctype.h>
  8.  
  9. #ifndef AMIGA
  10. #  include <sys/types.h>
  11. #endif /* AMIGA */
  12.  
  13. #include "fgetmfs.h"
  14. #include "libc.h"
  15.  
  16. #ifndef max
  17. # define max(a,b) ((a) > (b)? (a): (b))
  18. # define min(a,b) ((a) < (b)? (a): (b))
  19. #endif /* max */
  20.  
  21. /* One could make these arguments, with defaults. */
  22. #define INITLN 90        /* initial allocation per line */
  23. #define GROWLN 200        /* additional allocation size */
  24.  
  25. /* getseg returns */
  26. #define FAILED 0
  27. #define HITLIMIT 1
  28. #define OKAY 2
  29.  
  30. static unsigned sz;        /* bytes currently allocated (in line) */
  31. static int incr;        /* for sz */
  32. static char *line;        /* current allocation */
  33. static char *segment;    /* start of line segment in "line" */
  34. static char *morep;        /* last byte possibly containing input */
  35.  
  36. /*
  37.  *    `fget malloced, flagged string' with continuations and limit on bytes.
  38.  *    The limit is like fgets's; limit-1 bytes can be read.
  39.  *    -1 means "no limit".
  40.  */
  41.  
  42. char *fgetmfs(fp, limit, cont)
  43. FILE *fp;
  44. register int limit, cont;        /* honour \ continuations? */
  45. {
  46.     /* allocate room for an initial segment of a line */
  47.     sz = INITLN;
  48.     incr = GROWLN;
  49.     if (limit >= 0 && sz > limit)
  50.         sz = limit;
  51.     line = malloc(sz);
  52.     if (line == NULL)
  53.         return NULL;        /* no memory, can't go on */
  54.     segment = line;
  55.     morep = line + sz - 2;
  56.  
  57.     /* read all lines, including continuations */
  58.     do {
  59.         /* read the first segment of a line */
  60.         *morep = '\0';            /* mark end of segment */
  61.         if (fgets(segment, (int)sz-(segment-line), fp) == NULL) {
  62.             fprintf(stderr, "bytes read: '%.*s'\n",
  63.                 (int)sz - (segment - line), segment);
  64.             free(line);        /* EOF: give up */
  65.             return NULL;
  66.         }
  67.         /* read more of this line, if it didn't fit */
  68.         while (*morep != '\0' && *morep != '\n') {
  69.             register int code = getseg(fp, limit);
  70.  
  71.             if (code == FAILED)
  72.                 return NULL;
  73.             else if (code == HITLIMIT)
  74.                 break;
  75.         }
  76.     } while (cont && ismore(fp, cont));
  77.     return realloc(line, (unsigned)(strlen(line)+1));    /* save space */
  78. }
  79.  
  80. static int getseg(fp, limit)
  81. FILE *fp;
  82. register int limit;
  83. {
  84.     register int oldsz = sz;
  85.  
  86.     /* extend the allocation, within limit */
  87.     incr = GROWLN;
  88.     sz += incr;
  89.     if (limit >= 0 && sz > limit) {
  90.         sz = limit;
  91.         incr = sz - oldsz;
  92.     }
  93.     if (incr <= 0)            /* hit the limit? */
  94.         return HITLIMIT;
  95.     line = realloc(line, sz);
  96.     if (line == NULL)
  97.         return FAILED;        /* no memory, can't go on */
  98.     /* -1 starts on the terminating NUL of the prev. segment */
  99.     segment = line + oldsz - 1;
  100.     morep = line + sz - 2;        /* recompute for new line, sz */
  101.  
  102.     /* read the next segment */
  103.     *morep = '\0';
  104.     /* +1 because segment includes terminating NUL of the prev. segment */
  105.     if (fgets(segment, incr+1, fp) == NULL) {
  106.         free(line);        /* EOF: give up */
  107.         return FAILED;
  108.     }
  109.     return OKAY;
  110. }
  111.  
  112. static int
  113. ismore(fp, cont)
  114. register FILE *fp;
  115. int cont;
  116. {
  117.     register char *nlp;
  118.  
  119.     /* got a whole line: is it to be continued? */
  120.     if (incr > 0 && cont && (nlp = rindex(line, '\n')) != NULL &&
  121.         nlp > line && *--nlp == '\\') {
  122.         *nlp = '\0';            /* delete "\\\n" */
  123.         segment = nlp;
  124.             if (cont == CONT_NOSPC) {
  125.             register int c;
  126.  
  127.             /* discard leading whitespace */
  128.             while ((c = getc(fp)) != EOF && c != '\n' &&
  129.                isascii(c) && isspace(c))
  130.                 ;
  131.             if (c != EOF)
  132.                 (void) ungetc(c, fp);
  133.             }
  134.         return 1;            /* read next line */
  135.     } else
  136.         return 0;
  137. }
  138.